package uf.audit.db;

import java.sql.SQLException;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.UUID;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.jfinal.json.FastJson;
import com.jfinal.json.Json;
import com.jfinal.plugin.activerecord.*;

import redis.clients.jedis.Jedis;
import uf.audit.util.Consts;
import uf.audit.util.Table;
import uf.audit.util.Utils;

/**
 * 考试试卷实体
 *
 * @author sunny
 */
@Table(key = "testbh")
public class Test extends Model<Test> {
    private static final long serialVersionUID = -7644540082576539659L;
    public static Test dao = new Test().use(DbKit.MAIN_CONFIG_NAME);
    //定义全局的redis
    public Jedis jedis = new Jedis("localhost");

    // 容错处理 如果set的值为空，就不做处理
    @Override
    public Test set(String attr, Object value) {
        if (value != null) {
            super.set(attr, value);
        }
        return this;
    }

    // 删除某个模板对应的所有考试试卷
    public void deleteWithModelBh(String modelbh) {
        DbPro.use().update("delete from test where modelbh=?", modelbh);
    }

    // 获取某个人员某个考试的试卷信息
    public Test getTestWithModelBh(String userbh, String modelbh) {
        return findFirst("select * from test where modelbh=? and userbh=?", modelbh, userbh);
    }


    // 试卷是否被用于考试（考试模板被占用)
    public boolean modelbeused(String modelbh) {
        Test t = this.findFirst("select * from test where modelbh=? and userbh<>'--' and userbh<>'0000001'", modelbh);
        if (t != null) {
            return true;
        }
        return false;
    }

    // 根据编号获取某个考试试卷
    public Test gettest(String testbh) {
        return findFirst("select * from test where testbh=?", testbh);
    }

    //重置audittest的试卷的开始时间
    public void uaptest(String testbh) {
        DbPro.use().update("update test set starttime=NULL where testbh=?", testbh);
    }

    // 更新
    public boolean update(JSONObject obj) {
        String bh = obj.getString("testbh");
        Test item = new Test();
        item.set("modelbh", obj.getString("modelbh"));
        item.set("userbh", obj.getString("userbh"));
        item.set("starttime", obj.getString("starttime"));
        item.set("minutes", obj.getInteger("minutes"));
        item.set("finished", obj.getInteger("finished"));
        item.set("enabled", obj.getInteger("enabled"));
        boolean result = false;
        if (bh != null) {
            item.set("testbh", bh);
            result = item.update();
        } else {
            item.set("testbh", UUID.randomUUID().toString());
            result = item.save();
        }
        return result;
    }

    // 删除
    public boolean delete(String bh) {
        return deleteById(bh);
    }

    // 克隆试卷（从指定的考试模板）
    public Test cloneTestFromModel(final String modelbh, final String userbh) {
        final String testbh = UUID.randomUUID().toString();
        final Test t = new Test();
        if (DbPro.use().tx(new IAtom() {

            public boolean run() throws SQLException {
                Test mt = Test.dao.getTestWithModelBh(Consts.ADMIN_FIX, modelbh);
                TestModel tm = TestModel.dao.getplan(modelbh);

                t.set("modelbh", modelbh);
                t.set("userbh", userbh);
                t.set("starttime", Utils.getDateTime());
                t.set("minutes", tm.getInt("minutes"));
                t.set("testbh", testbh);
                // testbh
                String srcbh = mt.getStr("testbh");
                List<TestQuestion> qs = TestQuestion.dao.getquestions(srcbh);
                List<TestQuestion> nqs = new ArrayList<TestQuestion>();
                Set<Integer> exts = new HashSet<Integer>();
                for (TestQuestion q : qs) {
                    TestQuestion qi = new TestQuestion();
                    String testquestionbh = UUID.randomUUID().toString();
                    qi.set("testquestionbh", testquestionbh);
                    qi.set("testbh", testbh);
                    qi.set("itembh", q.getStr("itembh"));
                    qi.set("score", q.getInt("score"));
                    qi.set("itemtype", q.getStr("itemtype"));
                    qi.set("sortno", Utils.getRandNum(qs.size(), exts));
                    nqs.add(qi);
                }
                List<TestOpt> os = TestOpt.dao.getoptions(srcbh);
                List<TestOpt> nos = new ArrayList<TestOpt>();
                for (TestOpt o : os) {
                    TestOpt oi = new TestOpt();
                    String testoptbh = UUID.randomUUID().toString();
                    oi.set("testoptbh", testoptbh);
                    oi.set("testbh", testbh);
                    oi.set("itembh", o.getStr("itembh"));
                    oi.set("optbh", o.getStr("optbh"));
                    oi.set("itemtype", o.getStr("itemtype"));
                    oi.set("isanswer", o.getInt("isanswer"));
                    nos.add(oi);
                }
                for (TestQuestion q : nqs) {
                    q.save();
                }
                for (TestOpt o : nos) {
                    o.save();
                }
                t.save();
                return true;
            }
        }))
            return t;
        else
            return null;
    }

    public List<Record> gettestopts(String testbh) {
        String sql = "select * from (select a.*, b.score, b.sortno from (select a.*, b.optno, b.optcontent from (select a.testoptbh, a.testbh, a.itembh, a.optbh, b.itemtype, a.answer, b.itemcontent from (select * from testopt where testbh=?) a left join question b on a.itembh=b.itembh) a left join options b on a.optbh=b.optbh) a left join testquestion b on a.itembh=b.itembh and a.testbh=b.testbh) a where a.itemcontent<>'' order by a.sortno, a.optno";
        return DbPro.use().find(sql, testbh);
    }

    public List<Record> gettestoptswithstep(String testbh, int step) {
        String sql = "select * from (select a.*, b.score, b.sortno from (select a.*, b.optno, b.optcontent from (select a.testoptbh, a.testbh, a.itembh, a.optbh, b.itemtype, a.answer, b.itemcontent from (select * from testopt where testbh=?) a left join question b on a.itembh=b.itembh) a left join options b on a.optbh=b.optbh) a left join testquestion b on a.itembh=b.itembh and a.testbh=b.testbh) a where a.itemcontent<>'' and a.sortno=? order by optno asc";
        return DbPro.use().find(sql, testbh, step);
    }

    public boolean buildTest(final String modelbh, final Map<String, String> info) {
        return DbPro.use().tx(new IAtom() {

            public boolean run() throws SQLException {
                Test test = new Test();
                String testbh = UUID.randomUUID().toString();
                test.set("testbh", testbh);
                test.set("modelbh", modelbh);
                test.set("userbh", Consts.ADMIN_FIX);
                List<TestModelDetail> details = TestModelDetail.dao.getmodeldetails(modelbh);
                List<TestQuestion> testQs = new ArrayList<TestQuestion>();
                List<TestOpt> testOpts = new ArrayList<TestOpt>();
                for (TestModelDetail dt : details) {
                    /**
                     * detailbh varchar(50) comment '模板明细编号', modelbh
                     * varchar(50) comment '模板编号', seqbh varchar(50) comment
                     * '所属序列', catebh varchar(50) comment '所属分类', itemtype
                     * varchar(50) comment '题目类型', itemcount int default 10
                     * comment '题目数量', score int default 1 comment '每题的分数',
                     * itemlevel int default 0 comment '试题难度, 0..10'
                     */
                    String seqbh = dt.getStr("seqbh");
                    String catebh = dt.getStr("catebh");
                    String itemtype = dt.getStr("itemtype");
                    int itemcount = dt.getInt("itemcount");
                    int score = dt.getInt("score");
                    Integer itemlevel = dt.getInt("itemlevel");
                    List<Question> qs = Question.dao.getquestions(seqbh, catebh, itemtype, itemlevel);
                    Set<Integer> exsist = new HashSet<Integer>();
                    if (qs.size() < itemcount) {
                        info.put("error", String.format("%s 题目总数 %d 小于需要的题目数量 %d", itemtype, qs.size(), itemcount));
                        return false;
                    } else {
                        for (int i = 0; i < itemcount; i++) {
                            int idx = Utils.getRandNum(itemcount, exsist);
                            /**
                             * testbh varchar(50) comment '考试编号', itembh
                             * varchar(50) comment '题目编号', score int default 1
                             * comment '考题分数', itemtype varchar(50) comment
                             * '考题类型', sortno int comment '考题序号'
                             */
                            Question q = qs.get(idx);
                            String itembh = q.getStr("itembh");
                            TestQuestion tq = new TestQuestion();
                            String testquestionbh = UUID.randomUUID().toString();
                            tq.set("testquestionbh", testquestionbh);
                            tq.set("testbh", testbh);
                            tq.set("itembh", itembh);
                            tq.set("score", score);
                            tq.set("itemtype", itemtype);
                            tq.set("sortno", testQs.size());
                            testQs.add(tq);
                            /*
                             * testbh varchar(50), itembh varchar(50), optbh
                             * varchar(50), itemtype varchar(50) comment '考题类型',
                             * answer varchar(256) comment '答案', isanswer int
                             * default 0 comment '是否是答案'
                             */
                            List<Options> opts = Options.dao.getoptions(itembh);
                            for (Options o : opts) {
                                /*
                                 * optbh varchar(50) comment '答案编号', itembh
                                 * varchar(50) comment '所属试题', optcontent
                                 * varchar(256) comment '答案内容', optno char(1)
                                 * comment '答案号码：ABCD', isanswer int default 0
                                 * comment '是否是答案，0-不是，1是', remark varchar(256)
                                 */
                                TestOpt to = new TestOpt();
                                String testoptbh = UUID.randomUUID().toString();
                                to.set("testoptbh", testoptbh);
                                to.set("testbh", testbh);
                                to.set("itembh", itembh);
                                to.set("optbh", o.getStr("optbh"));
                                to.set("answer", o.getStr("answer"));
                                to.set("isanswer", o.getInt("isanswer"));
                                to.set("itemtype", itemtype);
                                testOpts.add(to);
                            }
                        }
                    }
                }
                test.save();
                for (TestQuestion tq : testQs) {
                    tq.save();
                }
                for (TestOpt opt : testOpts) {
                    opt.save();
                }
                TestModel m = TestModel.dao.getplan(modelbh);
                m.set("builded", 1);
                m.update();
                return true;
            }
        });
    }

    public List<Record> getquestionwithstep(String testbh, int step, String userbh) {
        String key = "" + userbh + "^" + testbh;
        List<String> is_exist = jedis.lrange(key, 0, 1000);
        if (is_exist.size() <= 0) {
            String sql = "select * from (select a.*, b.score, b.sortno from (select a.*, b.optno, b.optcontent from (select a.testoptbh, a.testbh, a.itembh, a.optbh, b.itemtype, a.answer,a.isanswer, b.itemcontent from (select * from testopt where testbh=?) a left join question b on a.itembh=b.itembh) a left join options b on a.optbh=b.optbh) a left join testquestion b on a.itembh=b.itembh and a.testbh=b.testbh) a where a.itemcontent<>''  order by sortno,optno asc";
            List<Record> list = DbPro.use().find(sql, testbh);
            String jsonstr = JSON.toJSONString(list);
            jedis.lpush(key, jsonstr);
            List<Record> firstquestion = new ArrayList<Record>();
            for (int i = 0; i < list.size(); i++) {
                if (list.get(i).getInt("sortno") == 0) {
                    firstquestion.add(list.get(i));
                }
            }
            return firstquestion;
        } else {
            List<Record> list = new ArrayList<Record>();
            for (int i = 0; i < is_exist.size(); i++) {
                String jsonstr = is_exist.get(0);
                JSONArray jsonArray = JSON.parseArray(jsonstr);
                for (int l = 0; l < jsonArray.size(); l++) {
                    JSONObject json = jsonArray.getJSONObject(l);//获取jsonobject
                    JSONObject jsonObject = json.getJSONObject("columns");//通过可以获取value
                    Record record = new Record().setColumns(FastJson.getJson().parse(jsonObject.toJSONString(), Map.class));
                    int sortno = record.getInt("sortno");
                    if (sortno == step) {
                        list.add(record);
                    }
                }
            }
            return list;
        }
    }
}
